using System;
using System.Collections.Generic;
using System.Text;

namespace Zsa.Emulation.Config
{
    /// <summary>
    /// The device settings.
    /// </summary>
    [Serializable()]
    public struct NesMachineSettings : ICloneable
    {

        #region Static 

        /// <summary>
        /// The ntsc fps.
        /// </summary>
        public const int NtscFps = 60;

        /// <summary>
        /// The pal fps.
        /// </summary>
        public const int PalFps = 50;

        /// <summary>
        /// The default nes speed.
        /// </summary>
        public const float DefaultSpeed = 1.0F;
        /// <summary>
        /// The tv format.
        /// </summary>
        public const TelevisionFormat DefaultTelevisionFormat = TelevisionFormat.Auto;

        /// <summary>
        /// Gets the default.
        /// </summary>
        /// <value>The default.</value>
        public static NesMachineSettings Default
        {
            get
            {
                return new NesMachineSettings(DefaultTelevisionFormat, DefaultSpeed, 0);
            }
        }
        #endregion Static

        #region Fields
        /// <summary>
        /// The device speed.
        /// </summary>
        private float _Speed;
        /// <summary>
        /// The maxium number of frame can skip.
        /// </summary>
        private int _MaxFrameSkip;
        /// <summary>
        /// The tv format.
        /// </summary>
        private TelevisionFormat _TelevisionFormat;
        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="DeviceSettings"/> class.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="defaultSpeed">The speed as a percentage</param>
        public NesMachineSettings(TelevisionFormat format,
            float speed, int maxFrameSkip)
        {
            if (speed < 0)
            {
                throw new ArgumentOutOfRangeException("speed", speed,
                    "The speed must be greater than zero !");
            }
            _TelevisionFormat = format;
            _Speed = speed;
            _MaxFrameSkip = maxFrameSkip;
        }
        #endregion Constructor

        #region Properties

        /// <summary>
        /// The speed in fps
        /// </summary>
        public float Speed
        {
            get 
            {
                return _Speed;
            }
            set
            {
                _Speed = value;   
            }
        }

        /// <summary>
        /// Gets the format.
        /// </summary>
        /// <value>The format.</value>
        public TelevisionFormat Format
        {
            get
            {
                return _TelevisionFormat;
            }
            set
            {
                _TelevisionFormat = value;
            }
        }



        #endregion Properties

        #region Methods

        /// <summary>
        /// Gets the fps.
        /// </summary>
        /// <param name="fileInfo">The file info.</param>
        /// <returns></returns>
        public float GetFramePerMillisecound(Cartridge.CartridgeFileInfo fileInfo)
        { 
            // Check arg.
            if ( fileInfo == null )
            {
                throw new ArgumentNullException("fileInfo","The file info cannot be null !");
            }
            //Temp format.
            TelevisionFormat _Format = _TelevisionFormat;
            // if set to auto.
            if (_Format == TelevisionFormat.Auto)
            {
                _Format = fileInfo.IsPal ?
                    TelevisionFormat.Pal : TelevisionFormat.Ntsc;
            }
            if (_Format == TelevisionFormat.Pal || _Format == TelevisionFormat.Ntsc)
            {
                // Return the fps.
                float _Fps =
                    ((_Format == TelevisionFormat.Ntsc ? NtscFps :
                    PalFps) / 1000F) * _Speed;
                return _Fps;
            }
            throw new ArgumentException();

        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            NesMachineSettings _Settings = new NesMachineSettings();
            _Settings._Speed = _Speed;
            return _Settings;
        }

        #endregion Methods
    }

    /// <summary>
    /// The tv format
    /// </summary>
    public enum TelevisionFormat
    {
        /// <summary>
        /// This is the default setting.  
        /// The format used depends on the game.
        /// </summary>
        Auto = 0,
        /// <summary>
        /// Force ntsc.
        /// </summary>
        Ntsc,
        /// <summary>
        /// Force pal.
        /// </summary>
        Pal
    }
}
